/**
 * HasUploadController.java
 */
package org.yate.oa.controller;

import java.io.File;
import java.io.IOException;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.web.multipart.MultipartFile;
import org.yate.oa.controller.FtpController.IWrapperFactory.FtpCallMethod;
import org.yate.oa.exception.FtpOperateException;
import org.yate.oa.model.FtpContent;
import org.yate.oa.service.FtpContentService;
import org.yate.oa.utils.Constants;
import org.yate.oa.utils.FileSuffixEnum;
import org.yate.oa.utils.FtpPathEnum;

/**
 * @author Yate
 * @date Jul 19, 2014
 * @description 有上传操作的基类
 * @version 1.0
 */
public abstract class FtpController<T extends FtpContent> extends
		BaseController {

	protected static FileSuffixEnum[] IMG_SUFFIX = new FileSuffixEnum[] {
			FileSuffixEnum.JPEG, FileSuffixEnum.JPG, FileSuffixEnum.PNG,
			FileSuffixEnum.GIF, FileSuffixEnum.BMP };

	@Value("${nfs.root.dir}")
	protected String ftpRootDir;

	public String getFtpRootDir() {
		return ftpRootDir;
	}

	@Resource
	protected FtpContentService ftpContentService;

	/**
	 * @author Yate
	 * @date Jul 19, 2014
	 * @description Ftp封装工厂
	 * @version 1.0
	 */
	public interface IWrapperFactory<T> {
		T getProduce(MultipartFile file, FtpCallMethod<T> call)
				throws IOException;

		T getProduce(MultipartFile file, String key) throws IOException;

		T getProduce(MultipartFile file) throws IOException;

		/**
		 * @author Yate
		 * @date Jul 19, 2014
		 * @description 工厂回调方法
		 * @version 1.0
		 */
		public interface FtpCallMethod<T> {
			void call(T t);
		}
	}

	@Component
	public static class WrapperFactory implements IWrapperFactory<FtpContent> {
		public FtpContent getProduce(MultipartFile file,
				FtpCallMethod<FtpContent> call) throws IOException {
			FtpContent c = new FtpContent();
			c.setType(file.getContentType());
			c.setLength(file.getSize());
			c.setMd5(DigestUtils.md5DigestAsHex(file.getBytes()));
			if (call != null) {
				call.call(c);
				// c.setValue(FilenameUtils.getName(file.getOriginalFilename()));
				c.setValue(DigestUtils.md5DigestAsHex(file.getBytes())
						+ "."
						+ FilenameUtils.getExtension(file.getOriginalFilename()));
			} else {
				c.setKey(FtpPathEnum.Temp.Path);
				c.setValue(DigestUtils.md5DigestAsHex(file.getBytes())
						+ "."
						+ FilenameUtils.getExtension(file.getOriginalFilename()));
			}
			return c;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * com.qianbao.car.controller.FtpController.IWrapperFactory#getProduce
		 * (org.springframework.web.multipart.MultipartFile, java.lang.String)
		 */
		@Override
		public FtpContent getProduce(MultipartFile file, String key)
				throws IOException {
			FtpContent c = new FtpContent();
			c.setType(file.getContentType());
			c.setLength(file.getSize());
			c.setMd5(DigestUtils.md5DigestAsHex(file.getBytes()));
			if (!StringUtils.isBlank(key)) {
				c.setKey(key);
				// c.setValue(FilenameUtils.getName(file.getOriginalFilename()));
				//c.setValue(DigestUtils.md5DigestAsHex(file.getBytes())
						//+ "."
						//+ FilenameUtils.getExtension(file.getOriginalFilename()));
				c.setValue(file.getOriginalFilename());
			} else {
				c.setKey(FtpPathEnum.Temp.Path);
				//c.setValue(DigestUtils.md5DigestAsHex(file.getBytes())
						//+ "."
						//+ FilenameUtils.getExtension(file.getOriginalFilename()));
				c.setValue(file.getOriginalFilename());
			}
			return c;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * com.qianbao.car.controller.FtpController.IWrapperFactory#getProduce
		 * (org.springframework.web.multipart.MultipartFile)
		 */
		@Override
		public FtpContent getProduce(MultipartFile file) throws IOException {
			FtpContent c = new FtpContent();
			c.setType(file.getContentType());
			c.setLength(file.getSize());
			c.setMd5(DigestUtils.md5DigestAsHex(file.getBytes()));
			c.setKey(FtpPathEnum.Temp.Path);
			c.setValue(DigestUtils.md5DigestAsHex(file.getBytes()) + "."
					+ FilenameUtils.getExtension(file.getOriginalFilename()));
			return c;
		}
	}

	protected abstract IWrapperFactory<T> getFactory();

	/**
	 * @description 校验上传文件的后缀
	 * @param file
	 * @param enums
	 * @return
	 */
	protected boolean validateFile(MultipartFile file, FileSuffixEnum... enums) {
		try {
			if (file == null || file.isEmpty()) {
				return false;
			}
			for (FileSuffixEnum t : enums) {
				if (StringUtils
						.equals(t.name().toUpperCase(), FilenameUtils
								.getExtension(file.getOriginalFilename())
								.toUpperCase())) {
					return true;
				}
			}
		} catch (Exception e) {
			super.log.error(e.getMessage(), e);
		}
		return false;
	}

	/**
	 * @description 校验上传文件的后缀
	 * @param fs
	 * @param enums
	 * @return
	 */
	protected boolean validateFiles(MultipartFile[] fs, FileSuffixEnum... enums) {
		boolean flag = false;
		for (MultipartFile file : fs) {
			try {
				if (file != null && !file.isEmpty()) {
					for (FileSuffixEnum t : enums) {
						if (StringUtils.equals(
								t.name().toUpperCase(),
								FilenameUtils.getExtension(
										file.getOriginalFilename())
										.toUpperCase())) {
							flag = true;
							break;
						}
					}
					if (!flag) {
						return false;
					}
				}
			} catch (Exception e) {
				super.log.error(e.getMessage(), e);
			}
		}
		return flag;
	}

	protected T wrapper(MultipartFile file) throws IOException {
		if (file == null || file.isEmpty()) {
			throw new NullPointerException();
		}
		return this.getFactory().getProduce(file);
	}

	protected T wrapper(MultipartFile file, FtpCallMethod<T> m)
			throws IOException {
		if (file == null || file.isEmpty()) {
			throw new NullPointerException();
		}
		return this.getFactory().getProduce(file, m);
	}

	protected T wrapper(MultipartFile file, String m) throws IOException {
		if (file == null || file.isEmpty()) {
			throw new NullPointerException();
		}
		return this.getFactory().getProduce(file, m);
	}

	protected void store(byte[] d, FtpContent e) throws FtpOperateException {
		try {
			File f = new File(ftpRootDir + e.getKey() + File.separator
					+ e.getValue());
			if (!f.exists()) {
				FileUtils.forceMkdir(new File(ftpRootDir + e.getKey()));
				FileUtils.touch(f);
				FileUtils.writeByteArrayToFile(f, d);
			}
		} catch (IOException ex) {
			log.error(ex.getMessage(), ex);
			throw new FtpOperateException("文件上传失败");
		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
			throw new FtpOperateException("文件上传失败");
		}
	}

	protected String formatDirSymbol(String target) {
		if (target == null || "".equals(target.trim()))
			return target;
		return target
				.replaceAll(Constants.WIN_FILE_PATH_SYMBOL, File.separator);
	}
}
